﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace SObject
{
    public class Serializer
    {
        class Constants
        {
            public class Xml
            {
                public const string ObjectElementToken = "Object";
                public const string ValueElementToken = "Value";
                public const string AttributeNameToken_Name = "Name";
            }
        }

        public Object LoadFromFile(Stream File, string CheckObjectName)
        {
            XDocument document;
            document = XDocument.Load(File);

            if (null != CheckObjectName)
            {
                if (false == IsResourceFileValid(document, CheckObjectName))
                {
                    string message = "Object name '" + CheckObjectName + "' does not match";
                    throw new SObject.Exception(message);
                }
            }

            XElement element = document.Root;
            string objectName = element.Attribute(Constants.Xml.AttributeNameToken_Name).Value;

            Object obj = ExtractObject(element);

            return (obj);
        }

        private bool IsResourceFileValid(XDocument ResourceFile, string CheckObjectName)
        {
            if (string.Empty != CheckObjectName)
            {
                if (Constants.Xml.ObjectElementToken != ResourceFile.Root.Name
                    || CheckObjectName != ResourceFile.Root.Attribute(Constants.Xml.AttributeNameToken_Name).Value)
                {
                    return false;
                }
            }
            return true;
        }

        private Object ExtractObject(XElement ObjectElement)
        {
            Object obj = new Object(ObjectElement.Attribute(Constants.Xml.AttributeNameToken_Name).Value);

            IEnumerable<XElement> valueList = ObjectElement.Elements(Constants.Xml.ValueElementToken);
            foreach (XElement valueElement in valueList)
            {
                obj.AddValue(valueElement.Value);
            }

            IEnumerable<XElement> children = ObjectElement.Elements(Constants.Xml.ObjectElementToken);
            foreach (XElement childElement in children)
            {
                Object child = ExtractObject(childElement);
                obj.AddChild(child);
            }

            return (obj);
        }
    }
}
